#include "common.h"
struct sockaddr_in *server_addr;
int socket_id = 0;
User my_user;

struct sockaddr_in *getAddrStruct(char *ip, short port);
void *revServerMessage(void *arg);
void manageUser();
void registerUser();
void loginUser();
void findPassword();
void seleteFunction();
void singleChat();
void groupChat();
void addFriend();
void deleteFriend();
void showChatRecords();
void sendFile();
void recvFile();

// 获取IP地址结构体(已验证)
struct sockaddr_in *getAddrStruct(char *ip, short port)
{
    // IP地址族结构体
    struct sockaddr_in *adr = malloc(sizeof(struct sockaddr_in));
    adr->sin_family = AF_INET; // IPV4网络地址

    // 把本地字节序的端口号转为网络字节序端口号
    adr->sin_port = htons(port);

    // 把字符串IP地址转为网络IP地址，并且存入指定结构体变量中
    inet_pton(AF_INET, ip, &adr->sin_addr);
    return adr;
}

// 接收服务器消息的线程(已验证)
void *revServerMessage(void *arg)
{
    while (1)
    {
        Message msg;
        if (read(socket_id, &msg, sizeof(msg)) <= 0)
        {
            printf("服务器已断开连接\n");
            break;
        }
        BLUE
            printf("%s\n", msg.time);
        RED
            printf("%s:", msg.msg_from.name);
        CLOSE
        printf("%s\n", msg.content);
    }
}

// 用户管理(已验证)
void manageUser()
{
    system("clear");
    while (1)
    {
        Message msg;
        int login_choice;
        printf("(1)注册 (2)登陆 (3)找回密码 (4)退出\n请选择:>");
        scanf("%d", &login_choice);
        if (login_choice == 1)
        {
            registerUser();
        }
        else if (login_choice == 2)
        {
            loginUser();
        }
        else if (login_choice == 3)
        {
            findPassword();
        }
        else if (login_choice == 4)
        {
            return;
        }
        else
        {
            printf("输入错误\n"); // 可能还需要清空输入缓冲区，避免死循环
            while (getchar() != '\n')
                ;
        }
    }
}

// 用户注册(已验证)
void registerUser()
{
    system("clear");
    Message msg;
    User user;
    printf("请输入账号:\n");
    scanf("%s", user.name);
    printf("请输入密码:\n");
    scanf("%s", user.password);
    printf("请输入密保问题:\n");
    scanf("%s", user.question);
    printf("请输入密保答案:\n");
    scanf("%s", user.answer);
    msg.msg_from = user;
    msg.type = REGISTER;
    write(socket_id, &msg, sizeof(msg));
    read(socket_id, &msg, sizeof(msg));
    if (!strcmp(msg.content, "OK"))
    {
        printf("注册成功！\n");
    }
    else
    {
        printf("注册失败！该用户已存在\n");
    }
}

// 用户登陆(已验证)
void loginUser()
{
    system("clear");
    Message msg;
    User user;
    printf("请输入账号:\n");
    scanf(" %s", user.name);
    printf("请输入密码:\n");
    scanf(" %s", user.password);
    msg.msg_from = user;
    msg.type = LOGIN;
    write(socket_id, &msg, sizeof(msg));
    read(socket_id, &msg, sizeof(msg));
    if (!strcmp(msg.content, "YES"))
    {
        printf("登陆成功\n");
        my_user = user;
        seleteFunction();
    }
    else if (!strcmp(msg.content, "REPET"))
    {
        printf("该用户正在登陆\n");
    }
    else
    {
        printf("用户名和密码错误\n");
    }
}

// 找回密码(已验证)
void findPassword()
{
    system("clear");
    Message msg;
    msg.type = FIND_PASSWORD;
    // 输入用户名
    printf("请输入要找回密码的用户名\n");
    scanf("%s", msg.msg_from.name);
    write(socket_id, &msg, sizeof(msg));
    // 判断用户是否存在
    read(socket_id, &msg, sizeof(msg));
    printf("%s\n", msg.content);
    if (!strcmp(msg.content, "未找到该用户"))
    {
        return;
    }
    // 输入密保答案
    scanf("%s", msg.msg_from.answer);
    write(socket_id, &msg, sizeof(msg));
    // 判断密保答案
    read(socket_id, &msg, sizeof(msg));
    if (strcmp(msg.content, "密保答案错误") == 0)
    {
        printf("密保答案错误\n");
        return;
    }
    // 输入新密码
    printf("请输入新密码\n");
    scanf("%s", msg.msg_from.password);
    write(socket_id, &msg, sizeof(msg));

    read(socket_id, &msg, sizeof(msg));
    if (!strcmp(msg.content, "密码修改成功"))
    {
        printf("密码修改成功\n");
    }
    else
    {
        printf("密码修改失败\n");
    }
}

// 功能选择界面(已验证)
void seleteFunction()
{
    system("clear");
    while (1)
    {
        int choice;
        Message msg;
        printf("(1)私聊 (2)群聊 (3)添加好友 (4)删除好友 (5)聊天记录 (6)上传文件 (7)下载文件 (8)返回上一级\n请选择:>");
        scanf("%d", &choice);
        if (choice == 1)
        {
            singleChat();
        }
        else if (choice == 2)
        {
            groupChat();
        }
        else if (choice == 3)
        {
            addFriend();
        }
        else if (choice == 4)
        {
            deleteFriend();
        }
        else if (choice == 5)
        {
            showChatRecords();
        }
        else if (choice == 6)
        {
            sendFile();
        }
        else if (choice == 7)
        {
            recvFile();
        }
        else if (choice == 8)
        {
            msg.type = EXIT;
            write(socket_id, &msg, sizeof(msg));
            return;
        }
        else
        {
            printf("输入错误\n");
            while (getchar() != '\n')
                ;
        }
    }
}

// 私聊功能(已验证)
void singleChat()
{
    system("clear");
    Message msg;
    msg.type = PRIVATE;
    msg.msg_from = my_user;
    printf("请输入聊天对象\n");
    scanf("%s", msg.msg_to.name);
    write(socket_id, &msg, sizeof(msg));

    read(socket_id, &msg, sizeof(msg));
    if (strcmp(msg.content, "YES") == 0)
    {
        printf("对方是你的好友，可以开始聊天了\n");
        pthread_t pt;
        pthread_create(&pt, NULL, revServerMessage, NULL);
        while (1)
        {
            msg.type = PRIVATE_CHAT;
            printf("请输入聊天内容(回车结束输入,quit返回上一级)\n");
            scanf("%s", msg.content);
            if (strcmp(msg.content, "quit") == 0)
            {
                pthread_cancel(pt);
                break;
            }
            write(socket_id, &msg, sizeof(msg));
        }
    }
    else
    {
        printf("对方不是你的好友，请添加好友后再试\n");
    }
}

// 群聊功能(已验证)
void groupChat()
{
    system("clear");
    Message msg;
    msg.type = GROUP;
    msg.msg_from = my_user;

    pthread_t pt;
    pthread_create(&pt, NULL, revServerMessage, NULL);
    while (1)
    {
        printf("请输入聊天内容(回车结束输入,quit返回上一级)\n");
        scanf("%s", msg.content);
        if (strcmp(msg.content, "quit") == 0)
        {
            pthread_cancel(pt);
            break;
        }
        write(socket_id, &msg, sizeof(msg));
    }
}

// 添加好友(已验证)
void addFriend()
{
    system("clear");
    Message msg;
    msg.type = ADD_FRIEND;
    msg.msg_from = my_user;
    printf("请输入要添加的好友\n");
    scanf("%s", msg.msg_to.name);
    write(socket_id, &msg, sizeof(msg));
    // 读取返回结果
    read(socket_id, &msg, sizeof(msg));
    if (!strcmp(msg.content, "ME"))
    {
        printf("不能添加自己为好友\n");
        return;
    }
    if (!strcmp(msg.content, "NO"))
    {
        printf("未找到该用户\n");
        return;
    }
    if (strcmp(msg.content, "YES") == 0)
    {
        printf("添加好友成功\n");
    }
}

// 删除好友(已验证)
void deleteFriend()
{
    system("clear");
    Message msg;
    msg.type = DELETE_FRIEND;
    msg.msg_from = my_user;
    printf("请输入要删除的好友\n");
    scanf("%s", msg.msg_to.name);
    write(socket_id, &msg, sizeof(msg));
    read(socket_id, &msg, sizeof(msg));
    if (!strcmp(msg.content, "NO"))
    {
        printf("不存在该好友\n");
        return;
    }
    if (strcmp(msg.content, "YES") == 0)
    {
        printf("删除好友成功\n");
    }
}

// 查看聊天记录(已验证)
void showChatRecords()
{
    system("clear");
    Message msg;
    msg.type = SHOW_RECONDS;
    msg.msg_from = my_user;
    write(socket_id, &msg, sizeof(msg));
    printf("你的聊天记录如下:\n");
    while (1)
    {
        read(socket_id, &msg, sizeof(msg));
        if (!strcmp(msg.content, "END"))
        {
            break;
        }
        BLUE
            printf("%s\n", msg.time);
        RED
            printf("%s:", msg.msg_to.name);
        CLOSE
        printf("%s\n", msg.content);
    }
}

// 上传文件
void sendFile()
{
    system("clear");
    Message msg;
    struct stat st;
    int complete_bytes; // 文件已发送的字节数
    int send_bytes;     // 文件本次发送的字节数
    msg.type = SEND_FILE;
    msg.msg_from = my_user;
    write(socket_id, &msg, sizeof(msg));

    File file;
    printf("请输入要发送文件的名称(quit退出)\n");
    scanf("%s", msg.msg_to.name);
    if (!strcmp(msg.msg_to.name, "quit"))
    {
        return;
    }
    int fd = open(msg.msg_to.name, O_RDONLY);
    stat(msg.msg_to.name, &st);

    while (1)
    {
        send_bytes = st.st_size - complete_bytes;
        if (send_bytes == 0)
        {
            break;
        }
        printf("已上传%.2f%%\n", complete_bytes / (float)st.st_size * 100);
        send_bytes = send_bytes > 1000 ? 1000 : send_bytes;
        complete_bytes += send_bytes;

        file.send_byte = send_bytes;
        read(fd, file.buf, send_bytes);
        memcpy(msg.content, &file, sizeof(file));

        write(socket_id, &msg, sizeof(msg));
    }
    msg.type = FILE_END;
    write(socket_id, &msg, sizeof(msg));
    printf("上传完成\n");
    close(fd);
}

// 下载文件
void recvFile()
{
    system("clear");
    Message msg;
    File *file;
    int recv_bytes = 0;
    msg.type = SHOW_FILE;
    write(socket_id, &msg, sizeof(msg));
    read(socket_id, &msg, sizeof(msg));
    printf("文件列表如下:\n%s\n", msg.content);

    printf("请输入要下载的文件名(quit退出)\n");
    scanf("%s", msg.msg_to.name);
    if (!strcmp(msg.msg_to.name, "quit"))
    {
        return;
    }
    msg.type = RECV_FILE;
    write(socket_id, &msg, sizeof(msg));
    int fd = open("client_recv.c", O_WRONLY | O_CREAT | O_TRUNC, 0666);
    while (1)
    {
        read(socket_id, &msg, sizeof(msg));
        if (msg.type == FILE_END)
        {
            break;
        }
        file = (File *)msg.content;
        recv_bytes += file->send_byte;
        printf("已下载%.2f%%\n", recv_bytes / (float)file->file_byte * 100);
        write(fd, file->buf, file->send_byte);
    }
    printf("下载完成\n");
}

// 主函数(已验证)
int main(int argc, char const *argv[])
{
    server_addr = getAddrStruct("192.168.30.27", 9000);
    socket_id = socket(AF_INET, SOCK_STREAM, 0);
    while (connect(socket_id, (struct sockaddr *)server_addr, sizeof(struct sockaddr)) == -1)
    {
        perror("连接服务器出错,重连中...\n");
        sleep(2);
    }
    manageUser();
    close(socket_id);
    free(server_addr);
    return 0;
}
